import { RuntimeModelError } from '@ibiz-template/core';
import {
  MDControlController,
  IDataViewControlEvent,
  IDataViewControlController,
  IDataViewControlState,
  ButtonContainerState,
  UIActionButtonState,
  UIActionUtil,
  IMDControlGroupState,
  CodeListItem,
  MDCtrlLoadParams,
} from '@ibiz-template/runtime';
import {
  IDEDataView,
  IDEDataViewItem,
  IUIActionGroupDetail,
} from '@ibiz/model-core';
import { DataViewControlService } from './data-view.service';

export class DataViewControlController
  extends MDControlController<
    IDEDataView,
    IDataViewControlState,
    IDataViewControlEvent
  >
  implements IDataViewControlController
{
  /**
   * 数据视图（卡片）部件服务
   *
   * @type {DataViewControlService}
   * @memberof DataViewControlController
   */
  declare service: DataViewControlService;

  /**
   * 初始化State
   *
   * @protected
   * @memberof DataViewControlController
   */
  protected initState(): void {
    super.initState();
    this.state.noSort = this.model.noSort === true;
  }

  /**
   * 初始化
   *
   * @protected
   * @return {*}  {Promise<void>}
   * @memberof DataViewControlController
   */
  protected async onCreated(): Promise<void> {
    await super.onCreated();
    this.state.size = this.model.pagingSize || 20;
    this.service = new DataViewControlService(this.model);
    await this.service.init(this.context);
  }

  /**
   * 加载更多
   *
   * @return {*}  {Promise<void>}
   * @memberof DataViewControlController
   */
  async loadMore(): Promise<void> {
    if (this.state.total > this.state.items.length) {
      await this.load({ isLoadMore: true });
    }
  }

  async afterLoad(args: MDCtrlLoadParams, items: IData[]): Promise<IData[]> {
    await this.handleDataGroup();
    return items;
  }

  /**
   * 获取操作项模型
   *
   * @return {*}  {(IDEDataViewItem | null)}
   * @memberof DataViewControlController
   */
  getOptItemModel(): IDEDataViewItem | null {
    let optItemModel: IDEDataViewItem | null = null;
    const { dedataViewItems } = this.model;
    if (dedataViewItems) {
      for (let index = 0; index < dedataViewItems.length; index++) {
        if (dedataViewItems[index].itemType === 'ACTIONITEM') {
          optItemModel = dedataViewItems[index];
        }
      }
    }
    return optItemModel;
  }

  /**
   * 获取操作项行为
   *
   * @param {IData} item
   * @return {*}
   * @memberof DataViewControlController
   */
  getOptItemAction(item: IData): ButtonContainerState {
    const containerState = new ButtonContainerState();
    const optItemModel = this.getOptItemModel();
    if (optItemModel) {
      if (!optItemModel.deuiactionGroup) {
        throw new RuntimeModelError(this.model, '操作项没有配置界面行为组');
      }
      if (!optItemModel.deuiactionGroup.uiactionGroupDetails?.length) {
        ibiz.log.debug('操作项界面行为组没有配置界面行为');
        return containerState;
      }
      optItemModel.deuiactionGroup.uiactionGroupDetails.forEach(detail => {
        const actionid = detail.uiactionId;
        if (actionid) {
          const buttonState = new UIActionButtonState(
            detail.id!,
            this.context.srfappid!,
            actionid,
          );
          containerState.addState(detail.id!, buttonState);
        }
      });
      containerState.update(item.getOrigin());
    }
    return containerState;
  }

  /**
   * 行为点击
   *
   * @param {IUIActionGroupDetail} detail
   * @param {IData} item
   * @param {MouseEvent} event
   * @return {*}  {Promise<void>}
   * @memberof DataViewControlController
   */
  async onActionClick(
    detail: IUIActionGroupDetail,
    item: IData,
    event: MouseEvent,
  ): Promise<void> {
    const actionId = detail.uiactionId;
    await UIActionUtil.execAndResolved(actionId!, {
      context: this.context,
      params: this.params,
      data: [item],
      view: this.view,
      event,
    });
  }

  /**
   * 处理数据分组
   *
   * @memberof DataViewControlController
   */
  async handleDataGroup(): Promise<void> {
    const { enableGroup, groupMode } = this.model;
    if (enableGroup && groupMode) {
      if (groupMode === 'AUTO') {
        this.handleAutoGroup();
      } else if (groupMode === 'CODELIST') {
        await this.handleCodeListGroup();
      }
    }
  }

  /**
   * 处理自动分组
   *
   * @memberof DataViewControlController
   */
  handleAutoGroup(): void {
    const { groupAppDEFieldId } = this.model;
    if (groupAppDEFieldId) {
      const { items } = this.state;
      const childrenMap: Map<string, IData[]> = new Map();
      items.forEach((item: IData) => {
        const children = childrenMap.get(item[groupAppDEFieldId]) || [];
        children.push(item);
        childrenMap.set(item[groupAppDEFieldId], children);
      });
      const groups: IMDControlGroupState[] = [];
      childrenMap.forEach((value: IData[], key: string) => {
        groups.push({
          caption: key,
          children: [...value],
        });
      });
      this.state.groups = groups;
    }
  }

  /**
   * 处理代码表分组
   *
   * @memberof DataViewControlController
   */
  async handleCodeListGroup(): Promise<void> {
    const { groupAppDEFieldId, groupCodeListId } = this.model;
    if (groupAppDEFieldId && groupCodeListId) {
      const { items } = this.state;
      const groups: IMDControlGroupState[] = [];
      const app = ibiz.hub.getApp(this.context.srfappid);
      const codeList = await app.codeList.get(
        groupCodeListId,
        this.context,
        this.params,
      );
      const keys: string[] = [];
      codeList.forEach((codeListItem: CodeListItem) => {
        const value = items.filter(
          (item: IData) => item[groupAppDEFieldId] === codeListItem.value,
        );
        groups.push({
          caption: codeListItem.text,
          children: [...value],
        });
        keys.push(codeListItem.value as string);
      });
      const otherGroup = items.filter(
        (item: IData) => keys.indexOf(item[groupAppDEFieldId]) === -1,
      );
      if (otherGroup.length > 0) {
        groups.push({
          caption: '其他',
          children: [...otherGroup],
        });
      }
      this.state.groups = groups;
    }
  }
}
